class Table {
  int * table;
  int * list;
  int DIM,N,N_LIST,N_WALK;
 public:
  int get_length();
  int hash_function(int * pos);
  void set_entry(int ent_num,int * pos);
  void get_entry(int ent_num, int * pos);
  void clear_table();
  void print_table();
  Table(int d,int n);              // table for positions of a d dimensional walk of n steps
  ~Table();
};

int Table::get_length() {
  return N/DIM;
}

int Table::hash_function(int *pos) {
  int i;
  float a,h;
  h=0;
  for (i=0;i<DIM;i++) {
    a=pow(float(abs(pos[i])*1000),float((i+1))/float((DIM+1)));
    h=h+a;
  }
  h = fmod(h+1,N/DIM);
  if (h>N) return 0;
  else return h;
}

void Table::get_entry(int ent_num, int * pos) {
  int i;
  for (i=ent_num*DIM;i<ent_num*DIM+DIM;i++) {
    pos[i-ent_num*DIM]=table[i];
  }
}

Table::Table(int d,int n) {
  int i;
  N_WALK=n;
  DIM=d;
  N=20*N_WALK*DIM;
  N_LIST=0;
  table = new int[N];
  list = new int[N_WALK+1];
  for (i=0;i<N;i++) {
    table[i]=123456789;
  }
  for (i=0;i<N_WALK+1;i++) {
    list[i]=-1;
  }
}

Table::~Table() {
  delete[] table;
  delete[] list;
}

void Table::set_entry(int ent_num,int * pos) {
  int i;
  for (i=ent_num*DIM;i<(ent_num+1)*DIM;i++) {
    table[i]=pos[i-ent_num*DIM];
  }
  list[N_LIST]=ent_num;
  N_LIST++;
}

void Table::clear_table() {
  int i,N_LIST2;
  int empty_pos[DIM];
  for (i=0;i<DIM;i++) {
    empty_pos[i]=123456789;
  }
  N_LIST2=N_LIST;
  N_LIST=0;
  for (i=0;i<N_LIST2;i++) {
    set_entry(list[i],empty_pos);
    list[i]=-1;
  }
  N_LIST=0;
}

void Table::print_table() {
  int i,j;
  cout << "list: ";
    for (i=0;i<N_LIST;i++) {
      cout << list[i] << " ";
      if (((i+1) % 10) == 0 ) cout << "\n";
    }
  cout << "\ntable: \n";
  for (i=0;i<N/DIM;i++) {
    for (j=0;j<DIM;j++) {
      cout << table[i*DIM+j] << "\t";
    }
    cout << "\n";
  }
  cout << "\n";
}

